package jmine.tec.di.wrapper;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import jmine.tec.annotations.Unmodifiable;
import jmine.tec.utils.Tuple;
import jmine.tec.utils.UnmodifiableTuple;

/**
 * Faz o wrapping em um mapa
 * 
 * @author MarceloT
 */
@Unmodifiable
class MapWrapper extends AbstractCollectionWrapper implements Wrapper {
    private static final long serialVersionUID = -9193226326670624960L;

    /**
     * Wrapp varios valores
     * 
     * @param propertyKeys os nomes das propriedades
     * @param propertyValues os valores das propriedades
     * @param valueType o tipo de valor
     * @return Object
     */
    public Object wrap(Object[] propertyKeys, Object[] propertyValues, Class<?> valueType) {
        final int amount = propertyKeys.length;
        Map<Object, Object> map = newMap(amount);
        for (int i = 0; i < propertyValues.length; i++) {
            Object object = propertyValues[i];
            Object name = propertyKeys[i];
            map.put(name, object);
        }
        return map;
    }

    /**
     * @param amount int
     * @return Map
     */
    protected Map<Object, Object> newMap(final int amount) {
        return new HashMap<Object, Object>(amount);
    }

    /**
     * Verifica se o tipo deste wrapper é compativel com o tipo de container passado
     * 
     * @param containerType Class
     * @return boolean
     */

    public boolean isTypeCompatible(Class<?> containerType) {
        return Map.class.isAssignableFrom(containerType);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected Collection<?> extractCollectionFrom(Object instance) {
        Map<?, ?> map = (Map<?, ?>) instance;
        return map.values();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Tuple<?, ?>> collect(Object resolved, String name) {
        Map<?, ?> map = (Map<?, ?>) resolved;
        List<Tuple<?, ?>> list = new ArrayList<Tuple<?, ?>>();
        Set<?> entrySet = map.entrySet();
        for (Object object : entrySet) {
            Entry<?, ?> entry = (Entry<?, ?>) object;
            list.add(UnmodifiableTuple.newTuple(entry.getKey(), entry.getValue()));
        }
        return list;
    }

}
